package net.neptech.listener.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import net.neptech.model.dto.InstanceRecordParamDto;
import net.neptech.listener.AbstractEventListenerStrategy;
import net.neptech.service.RemoteService;
import net.neptech.util.ExecutionUtil;
import net.neptech.util.FlowableUtil;
import net.neptech.util.JsonUtil;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.event.impl.FlowableProcessStartedEventImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;
import static net.neptech.enums.workflow.InstanceConstant.VariableKey.*;

/**
 * 流程开始了
 */
@Slf4j
@Component
public class ProcessStartedEventListener extends AbstractEventListenerStrategy implements InitializingBean {
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private RemoteService remoteService;
    /**
     * 处理数据
     */
    @Override
    public void handle(FlowableEvent event) {
        //流程开始了
        FlowableProcessStartedEventImpl flowableProcessStartedEvent = (FlowableProcessStartedEventImpl) event;
        ExecutionEntityImpl entity = (ExecutionEntityImpl) flowableProcessStartedEvent.getEntity();
        DelegateExecution execution = flowableProcessStartedEvent.getExecution();
        String flowId = entity.getProcessDefinitionKey();
        //上级实例id 主要是涉及到子流程的
        String nestedProcessInstanceId = flowableProcessStartedEvent.getNestedProcessInstanceId();
        {
            //设置唯一id
            String s = IdUtil.fastSimpleUUID();
            redisTemplate.opsForZSet().add(StrUtil.format(REDIS_KEY_OF_FLOW_UNIQUE_ID, entity.getProcessInstanceId()), StrUtil.format("{}||||{}", START_NODE, s), System.currentTimeMillis());
        }
        String processInstanceId = flowableProcessStartedEvent.getProcessInstanceId();
        String startUserId = FlowableUtil.getStartUserId(execution);
        log.info("发起人id：{}", startUserId);
        Map<String, Object> variables = execution.getVariables();
        String tenantId = entity.getTenantId();
        {
            //流程编号
            String processInstanceBizCode = StrUtil.format("BIZ{}{}", DateUtil.format(new Date(), "yyyyMMddHHmmss"), RandomUtil.randomStringUpper(6));
            RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class);
            runtimeService.setVariable(processInstanceId, PROCESS_INSTANCE_CODE, processInstanceBizCode);

            InstanceRecordParamDto instanceRecordParamDto = new InstanceRecordParamDto();
            instanceRecordParamDto.setUserId(startUserId);
            instanceRecordParamDto.setMainDeptId(MapUtil.getStr(variables, START_USER_MAIN_DEPTID_KEY));
            instanceRecordParamDto.setParentProcessInstanceId(nestedProcessInstanceId);
            instanceRecordParamDto.setFlowId(flowId);
            instanceRecordParamDto.setProcessInstanceId(processInstanceId);
            instanceRecordParamDto.setProcessInstanceBizKey(entity.getProcessInstanceBusinessKey());
            instanceRecordParamDto.setProcessInstanceBizCode(processInstanceBizCode);
            instanceRecordParamDto.setFormData(JsonUtil.toJSONString(variables));
            //判断是子流程启动
            if (StrUtil.isNotBlank(nestedProcessInstanceId)) {
                String superExecutionId = execution.getParent().getSuperExecutionId();
                String parentExecutionId = ExecutionUtil.getParentExecutionId(superExecutionId);
                instanceRecordParamDto.setParentProcessNodeExecutionId(parentExecutionId);
            }
            remoteService.processStartEvent(instanceRecordParamDto);
        }
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        afterPropertiesSet(FlowableEngineEventType.PROCESS_STARTED.toString());
    }
}
